<template>
  <el-form ref="ruleForm" :model="form" :rules="rules" class="phone-code-wrap">
    <div v-if="title" class="title">{{ title }}</div>
    <div class="form-model-wrap">
      <el-form-item prop="phone">
        <el-input v-model.trim="form.phone" size="large" placeholder="请输入手机号" :maxLength="11" class="phone-input">
          <el-icon slot="prefix" type="phone" />
        </el-input>
      </el-form-item>
      <div style="display: flex">
        <el-form-item prop="verificationCode">
          <el-input v-model.trim="form.verificationCode" size="large" placeholder="请输入验证码" :maxLength="4">
          </el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" :disabled="!!smsCount" class="captach-type" @click="onSmsCaptcha">
            {{ smsCount ? `${smsCount}s` : '获取验证码' }}
          </el-button>
        </el-form-item>
      </div>
      <el-button class="next-btn" type="primary" @click="goNext">下一步</el-button>
    </div>
    <Verify
      @success="verifySuccess"
      :isShow="isVerifyCodeShow"
      :imgSize="{ width: '330px', height: '155px' }"
      :getUrl="'/uc/api/captcha/get'"
      :checkUrl="'/uc/api/captcha/check'"
      :gateway="gateway"
      ref="verify"
    />
  </el-form>
</template>

<script lang="ts">
import { defineComponent, reactive, ref, onMounted, onUnmounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import * as Verify from 'if-verify'
import 'if-verify/dist/if-verify.css'
import { Regex } from '@/utils/validator'
import { commonValidate } from '@/utils/utils'
import { LoginRequest } from '@/services/login'
import { ACCOUNT_TYPE_MAP, CERTIFICATION_TYPE_MAP, LOGIN_TYPE_MAP, LOGIN_METHOD_MAP } from '@/global-config/const'
import { countDownInterval, browserTabChangeHandler, browserTabChangeListener } from '@/utils/count-down'
import { forgetSmsCache } from '../config'

export default defineComponent({
  name: 'phoneCode',
  props: {
    title: {
      type: String,
      default: '',
    },
    updatePasswordCode: {
      type: Function,
      default: () => () => {},
    },
  },
  components: {
    Verify,
  },
  setup() {
    // ---------------------- 变量 -----------------------
    const router = useRouter()
    const route = useRoute()
    const ruleForm = ref<any>()
    const form = ref<any>({
      accountType: ACCOUNT_TYPE_MAP.phoneCode,
      verificationCode: '',
      phone: '',
    })
    const rules = reactive<any>({
      phone: [
        {
          required: true,
          trigger: 'blur',
          validator: onCheckPhone,
        },
      ],
      verificationCode: [
        {
          required: true,
          trigger: 'blur',
          validator: onCheckCode,
        },
      ],
    })
    const smsCount = ref<number>(0) // sms短信验证码倒计时
    const smsTimer = ref<any>(null) // 定时器
    const isVerifyCodeShow = ref<boolean>(false)
    const gateway = import.meta.env.VITE_BASE_URL
    // ---------------------- 函数 -----------------------
    // 校验手机号
    function onCheckPhone(rule: any, value: any, callback: Function) {
      if (!value) {
        callback('请输入手机号')
        return
      }
      if (!Regex.phone.test(value)) {
        callback('请输入正确格式的手机号')
        return
      }
      callback()
    }
    // 校验验证码
    function onCheckCode(rule: any, value: any, callback: Function) {
      if (!value) {
        callback('请输入验证码')
        return
      }
      if (!Regex.verificationCode.test(value)) {
        callback('请输入正确格式的验证码')
        return
      }
      callback()
    }
    // 滑块验证
    const onSmsCaptcha = async () => {
      // 1. 校验手机号
      if (!Regex.phone.test(form.value.phone)) {
        return
      }
      // 2. 滑块验证码
      isVerifyCodeShow.value = !isVerifyCodeShow.value
    }
    // 验证码成功的回调
    const verifySuccess = async (token: any) => {
      const { phone, accountType } = form.value
      const params = {
        phone,
        accountType,
        cerificationType: CERTIFICATION_TYPE_MAP.resetForgetPwd,
        captchaVerification: token?.captchaVerification,
        loginType: LOGIN_TYPE_MAP.code,
        loginMethod: LOGIN_METHOD_MAP.phone,
      }
      const phoneValidateResult = await commonValidate(ruleForm.value, 'phone')
      if (!phoneValidateResult) return
      const smsResult = await LoginRequest.getLoginCode(params)
      const { code, data } = smsResult
      if (code !== 200) {
        return
      }
      form.value.verificationCode = data?.smsCode || ''
      // 获取之后，清理当前报错信息
      form.value.verificationCode && ruleForm.value.validateField('verificationCode') // 获取验证码后，重新校验
      countDownInterval({ smsCount, smsTimer }, true, forgetSmsCache) // 倒计时处理
    }
    // 下一步
    const goNext = async () => {
      const validateResult = await commonValidate(ruleForm.value)
      if (!validateResult) return
      const { verificationCode, phone, accountType } = form.value
      const params = {
        verificationCode,
        phone,
        accountType,
        cerificationType: CERTIFICATION_TYPE_MAP.resetForgetPwd,
      }
      const nextResult = await LoginRequest.checkPhoneSmsCode(params)
      const { code, data } = nextResult
      if (code !== 200) return
      // 这里是忘记密码的配置
      const query = {}
      Object.assign(query, route.query, { authorizationCode: data, phone })
      router.push({ query })
    }
    // tab变化监听
    const browserTabChange = () => {
      browserTabChangeHandler({ smsCount, smsTimer }, forgetSmsCache)
    }
    // ---------------------- 事件 -----------------------
    onMounted(() => {
      const params = { smsCount, smsTimer }
      countDownInterval(params, false, forgetSmsCache) // 倒计时处理
      browserTabChangeListener(true, { ...params, browserTabChange }) // 监听tab
    })
    onUnmounted(() => {
      browserTabChangeListener(false, { smsTimer, browserTabChange }) // 移除监听tab
    })
    // ---------------------- 返回 -----------------------
    return {
      ruleForm,
      form,
      rules,
      smsCount,
      isVerifyCodeShow,
      gateway,
      // methods
      onSmsCaptcha,
      verifySuccess,
      goNext,
    }
  },
})
</script>

<style lang="less" scoped>
.phone-code-wrap {
  width: 500px;
  margin: 0 auto;
  .title {
    width: 200px;
    font-size: 48px;
    text-align: center;
    font-weight: 700;
    color: #212121;
    width: 100%;
    line-height: 100px;
    padding-bottom: 30px;
  }
  .next-btn {
    font-size: 20px;
    font-weight: 500;
    width: 450px;
    height: 50px;
    border-radius: 100px;
    margin: 20px auto 0;
  }
  .phone-input {
    width: 500px;
  }
  .captach-type {
    margin-left: 20px;
  }
}
</style>
